package com.zmn.oms.zmn.business.impl.entrust;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.common.utils.http.HttpUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.oms.common.constant.OpenApiConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.entrust.SyncEntrustOrderStatusDTO;
import com.zmn.oms.model.dto.open.v2.*;
import com.zmn.oms.model.entity.dict.ChannelEntrustInterface;
import com.zmn.oms.model.entity.entrust.EntrustOrder;
import com.zmn.oms.services.interfaces.dict.ChannelEntrustInterfaceService;
import com.zmn.oms.services.interfaces.entrust.EntrustOrderService;
import com.zmn.oms.zmn.business.interfaces.entrust.EntrustOrderNotifyBService;
import com.zmn.oms.zmn.utils.open.OpenApiUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.Op;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 类描述：
 *
 * @author lhl
 * @date 2019/12/30 15:26
 */
@Slf4j
@Service("entrustOrderNotifyBService")
public class EntrustOrderNotifyBServiceImpl implements EntrustOrderNotifyBService {

    @Resource
    private ChannelEntrustInterfaceService channelEntrustInterfaceService;
    @Autowired
    private EntrustOrderService entrustOrderService;

    @Override
    public SyncEntrustOrderStatusDTO preparePushNewOrder(PushOrderDTO pushOrderDTO) throws OmsBaseException {
        Long orderId = Long.parseLong(pushOrderDTO.getOrderId());
        EntrustOrder dbEntrustOrder = entrustOrderService.findByKey(orderId);
        if (dbEntrustOrder == null) {
            throw new OmsBaseException("订单不存在");
        }

        ChannelEntrustInterface channel = channelEntrustInterfaceService.findByChannelId(dbEntrustOrder.getChannelToId());
        if (channel == null || channel.getStatus() != 2 || StringUtils.isBlank(channel.getInterfaceUrl())) {
            throw new OmsBaseException("渠道不存在或该渠道未开通同步新单");
        }

        // 封装推送新单请求参数
        PushNewOrderDTO pushNewOrderDTO = new PushNewOrderDTO();
        pushNewOrderDTO.setOrderId(String.valueOf(orderId));
        pushNewOrderDTO.setCreateTime(String.valueOf(dbEntrustOrder.getCreateTime().getTime()/1000));
        pushNewOrderDTO.setServiceType(dbEntrustOrder.getServCategId());
        pushNewOrderDTO.setUserName(dbEntrustOrder.getUserName());
        pushNewOrderDTO.setUserPhone(dbEntrustOrder.getUserPhone());
        pushNewOrderDTO.setCityId(String.valueOf(dbEntrustOrder.getCityId()));
        pushNewOrderDTO.setAddress(dbEntrustOrder.getAddress());
        pushNewOrderDTO.setStreet(dbEntrustOrder.getStreet());
        pushNewOrderDTO.setLatitude(dbEntrustOrder.getLatitude());
        pushNewOrderDTO.setLongitude(dbEntrustOrder.getLongitude());
        pushNewOrderDTO.setRemark(dbEntrustOrder.getRemark());
        // 产品
        PushNewOrderDTO.Product product = new PushNewOrderDTO.Product();
        product.setProductId(String.valueOf(dbEntrustOrder.getProductId()));
        product.setProductName(dbEntrustOrder.getProductName());
        product.setCount(dbEntrustOrder.getProductNumber());
        pushNewOrderDTO.setProducts(Lists.newArrayList(product));
        // 准备请求参数
        Map<String, String> params = OpenApiUtil.newV2RequestParams(channel.getChannelId(),
                channel.getAppSecret(), OpenApiConsts.FUNID_NEW_ORDER, pushNewOrderDTO);
        String pushUrl = channel.getInterfaceUrl();

        try {
            // 同步数据
            log.info("[EntrustOrder-pushNewOrder-request] orderId=[{}], url=[{}], data=[{}]",
                    orderId, pushUrl, JSON.toJSONString(params));
            String response = HttpUtil.post(pushUrl, params);
            log.info("[EntrustOrder-pushNewOrder-response] orderId=[{}], response=[{}]", orderId, response);

            ResultDTO resultDTO = null;
            try {
                resultDTO = JSON.parseObject(response, ResultDTO.class);
            } catch (Exception e) {
                String errorMsg = StringUtils.isBlank(response) ? "新委托单推送失败"
                        : String.format("新委托单推送失败 Response=[%s]", response);
                throw new OmsBaseException(errorMsg);
            }

            if (!Objects.equals(200, resultDTO.getStatus())) {
                throw new OmsBaseException(Optional.ofNullable(resultDTO.getMessage()).orElse(response));
            }
        } catch (Exception ex) {
            throw new OmsBaseException("新委托单推送失败");
        }

        // 更新委派时间对象
        EntrustOrder updateEntrustOrder = new EntrustOrder();
        updateEntrustOrder.setEntrustId(orderId);
        updateEntrustOrder.setEntrustTime(new Date());
        updateEntrustOrder.setUpdater("系统");

        // 封装准备入库的数据
        SyncEntrustOrderStatusDTO dto = new SyncEntrustOrderStatusDTO();
        dto.setPushOrderDTO(pushOrderDTO);
        dto.setDbEntrustOrder(dbEntrustOrder);
        dto.setEntrustOrder(updateEntrustOrder);

        return dto;
    }

    @Override
    @Transactional
    public ResultDTO doPushNewOrder(SyncEntrustOrderStatusDTO syncEntrustOrderStatusDTO) {
        try {
            EntrustOrder updateEntrustOrder = syncEntrustOrderStatusDTO.getEntrustOrder();
            entrustOrderService.updateByKey(updateEntrustOrder);
            return ResultDTO.success();
        } catch (Exception ex) {
            return ResultDTO.fail(ex.getMessage());
        }
    }

    @Override
    public SyncEntrustOrderStatusDTO prepareSyncDutyTime(PushDutyTimeDTO pushDutyTimeDTO) throws OmsBaseException {
        // 校验、准备参数
        Long orderId = null;
        Date dutyTime = null;
        {
            try {
                orderId = Long.parseLong(pushDutyTimeDTO.getOrderId());
                dutyTime = new Date(pushDutyTimeDTO.getDutyTime() * 1000);
            } catch (Exception e) {
                throw new OmsBaseException("参数格式有误", e);
            }

            // 预约时间不能在同步时间以前
            if (pushDutyTimeDTO.getDutyTime() < pushDutyTimeDTO.getOptTime()) {
                throw new OmsBaseException("预约时间不能小于同步时间");
            }
        }

        // 校验订单是否存在
        EntrustOrder dbEntrustOrder = validateEntrustOrderExist(orderId);
        // 状态校验：已完成、已取消状态不支持修改预约时间
        Integer status = dbEntrustOrder.getStatus();
        if (Objects.equals(OrderStatusConsts.ORDER_STATUS_COMPLETE, status)
                || Objects.equals(OrderStatusConsts.ORDER_STATUS_CANCEL, status)) {
            throw new OmsBaseException("已完成或已取消的订单不支持修改预约时间");
        }

        // 封装准备入库的数据
        SyncEntrustOrderStatusDTO dto = new SyncEntrustOrderStatusDTO();
        {
            dto.setDbEntrustOrder(dbEntrustOrder);
            // 委托单
            EntrustOrder updateEntrustOrder = new EntrustOrder();
            updateEntrustOrder.setEntrustId(orderId);
            updateEntrustOrder.setDutyTime(dutyTime);
            updateEntrustOrder.setStatus(OrderStatusConsts.ORDER_STATUS_CONFIRM);
            updateEntrustOrder.setUpdater("渠道");
            dto.setEntrustOrder(updateEntrustOrder);
        }

        return dto;
    }

    @Override
    @Transactional
    public ResultDTO doSyncDutyTime(SyncEntrustOrderStatusDTO syncEntrustOrderStatusDTO) {
        updateEntrustOrderById(syncEntrustOrderStatusDTO.getEntrustOrder());
        return ResultDTO.success();
    }

    @Override
    public SyncEntrustOrderStatusDTO prepareSyncMasterInfo(PushMasterInfoDTO pushMasterInfoDTO) throws OmsBaseException {
        // 校验、准备参数
        Long orderId = null;
        Date optTime = null;
        {
            try {
                orderId = Long.parseLong(pushMasterInfoDTO.getOrderId());
                optTime = new Date(pushMasterInfoDTO.getOptTime() * 1000);
            } catch (Exception e) {
                throw new OmsBaseException("参数格式有误", e);
            }
        }

        // 校验订单是否存在
        EntrustOrder dbEntrustOrder = validateEntrustOrderExist(orderId);
        // 状态校验：已完成、已取消状态不支持修改接单工程师
        Integer status = dbEntrustOrder.getStatus();
        if (Objects.equals(OrderStatusConsts.ORDER_STATUS_COMPLETE, status)
                || Objects.equals(OrderStatusConsts.ORDER_STATUS_CANCEL, status)) {
            throw new OmsBaseException("已完成或已取消的订单不支持修改接单工程师");
        }

        // 封装准备入库的数据
        SyncEntrustOrderStatusDTO dto = new SyncEntrustOrderStatusDTO();
        {
            dto.setDbEntrustOrder(dbEntrustOrder);
            // 委托单
            EntrustOrder updateEntrustOrder = new EntrustOrder();
            updateEntrustOrder.setEntrustId(orderId);
            updateEntrustOrder.setMasterName(pushMasterInfoDTO.getMasterName());
            updateEntrustOrder.setMasterPhone(pushMasterInfoDTO.getMasterPhone());
            updateEntrustOrder.setTakeTime(optTime);
            updateEntrustOrder.setStatus(OrderStatusConsts.ORDER_STATUS_TAKE);
            updateEntrustOrder.setUpdater("渠道");
            dto.setEntrustOrder(updateEntrustOrder);
        }

        return dto;
    }

    @Override
    @Transactional
    public ResultDTO doSyncMasterInfo(SyncEntrustOrderStatusDTO syncEntrustOrderStatusDTO) {
        updateEntrustOrderById(syncEntrustOrderStatusDTO.getEntrustOrder());
        return ResultDTO.success();
    }

    @Override
    @SuppressWarnings("all")
    public SyncEntrustOrderStatusDTO prepareSyncMasterVisit(PushOrderDTO pushOrderDTO) throws OmsBaseException {
        // 校验、准备参数
        Long orderId = null;
        Date optTime = null;
        {
            try {
                orderId = Long.parseLong(pushOrderDTO.getOrderId());
                optTime = new Date(pushOrderDTO.getOptTime() * 1000);
            } catch (Exception e) {
                throw new OmsBaseException("参数格式有误", e);
            }
        }

        // 校验订单是否存在
        EntrustOrder dbEntrustOrder = validateEntrustOrderExist(orderId);
        // 状态校验：已完成、已取消状态不支持修改工程师上门
        Integer status = dbEntrustOrder.getStatus();
        if (Objects.equals(OrderStatusConsts.ORDER_STATUS_COMPLETE, status)
                || Objects.equals(OrderStatusConsts.ORDER_STATUS_CANCEL, status)) {
            throw new OmsBaseException("已完成或已取消的订单不支持修改工程师上门");
        }

        // 封装准备入库的数据
        SyncEntrustOrderStatusDTO dto = new SyncEntrustOrderStatusDTO();
        {
            dto.setDbEntrustOrder(dbEntrustOrder);
            // 委托单
            EntrustOrder updateEntrustOrder = new EntrustOrder();
            updateEntrustOrder.setEntrustId(orderId);
            updateEntrustOrder.setVisitTime(optTime);
            updateEntrustOrder.setStatus(OrderStatusConsts.ORDER_STATUS_VISIT);
            updateEntrustOrder.setUpdater("渠道");
            dto.setEntrustOrder(updateEntrustOrder);
        }

        return dto;
    }

    @Override
    @Transactional
    public ResultDTO doSyncMasterVisit(SyncEntrustOrderStatusDTO syncEntrustOrderStatusDTO) {
        updateEntrustOrderById(syncEntrustOrderStatusDTO.getEntrustOrder());
        return ResultDTO.success();
    }

    @Override
    @SuppressWarnings("all")
    public SyncEntrustOrderStatusDTO prepareSyncOrderComplete(PushOrderCompleteDTO pushOrderCompleteDTO)
            throws OmsBaseException {
        // 校验、准备参数
        Long orderId = null;
        Date optTime = null;
        {
            try {
                orderId = Long.parseLong(pushOrderCompleteDTO.getOrderId());
                optTime = new Date(pushOrderCompleteDTO.getOptTime() * 1000);
            } catch (Exception e) {
                throw new OmsBaseException("参数格式有误", e);
            }
        }

        // 校验订单是否存在
        EntrustOrder dbEntrustOrder = validateEntrustOrderExist(orderId);
        // 状态校验：已取消状态不能改成已完成
        Integer status = dbEntrustOrder.getStatus();
        if (Objects.equals(OrderStatusConsts.ORDER_STATUS_CANCEL, status)) {
            throw new OmsBaseException("已取消的订单不允许更改为完成状态");
        }
        // 状态校验：不能重复完成
        else if (Objects.equals(OrderStatusConsts.ORDER_STATUS_COMPLETE, status)) {
            throw new OmsBaseException("已完成订单不能再次操作完成");
        }

        // 封装准备入库的数据
        SyncEntrustOrderStatusDTO dto = new SyncEntrustOrderStatusDTO();
        {
            dto.setDbEntrustOrder(dbEntrustOrder);
            // 委托单
            EntrustOrder updateEntrustOrder = new EntrustOrder();
            updateEntrustOrder.setEntrustId(orderId);
            updateEntrustOrder.setCompleteTime(optTime);
            updateEntrustOrder.setStatus(OrderStatusConsts.ORDER_STATUS_COMPLETE);
            // 订单金额
            if (NumberUtil.isNotNullOrZero(pushOrderCompleteDTO.getBill())) {
                updateEntrustOrder.setTotalAmount(pushOrderCompleteDTO.getBill());
            }
            updateEntrustOrder.setUpdater("渠道");

            dto.setEntrustOrder(updateEntrustOrder);
        }

        return dto;
    }

    @Override
    @Transactional
    public ResultDTO doSyncOrderComplete(SyncEntrustOrderStatusDTO syncEntrustOrderStatusDTO) {
        updateEntrustOrderById(syncEntrustOrderStatusDTO.getEntrustOrder());
        return ResultDTO.success();
    }

    @Override
    @SuppressWarnings("all")
    public SyncEntrustOrderStatusDTO prepareSyncOrderCancel(PushOrderDTO pushOrderDTO) throws OmsBaseException {
        // 校验、准备参数
        Long orderId = null;
        Date optTime = null;
        {
            try {
                orderId = Long.parseLong(pushOrderDTO.getOrderId());
                optTime = new Date(pushOrderDTO.getOptTime() * 1000);
            } catch (Exception e) {
                throw new OmsBaseException("参数格式有误", e);
            }
        }

        // 校验订单是否存在
        EntrustOrder dbEntrustOrder = validateEntrustOrderExist(orderId);
        // 状态校验：已完成订单不能改成已取消
        Integer status = dbEntrustOrder.getStatus();
        if (Objects.equals(OrderStatusConsts.ORDER_STATUS_COMPLETE, status)) {
            throw new OmsBaseException("已完成的订单不允许更改为取消状态");
        }
        // 状态校验：不能重复完成
        else if (Objects.equals(OrderStatusConsts.ORDER_STATUS_CANCEL, status)) {
            throw new OmsBaseException("已取消订单不能再次操作取消");
        }

        // 封装准备入库的数据
        SyncEntrustOrderStatusDTO dto = new SyncEntrustOrderStatusDTO();
        {
            dto.setDbEntrustOrder(dbEntrustOrder);
            // 委托单
            EntrustOrder updateEntrustOrder = new EntrustOrder();
            updateEntrustOrder.setEntrustId(orderId);
            updateEntrustOrder.setCancelTime(optTime);
            updateEntrustOrder.setStatus(OrderStatusConsts.ORDER_STATUS_CANCEL);
            updateEntrustOrder.setUpdater("渠道");
            dto.setEntrustOrder(updateEntrustOrder);
        }

        return dto;
    }

    @Override
    @Transactional
    public ResultDTO doSyncOrderCancel(SyncEntrustOrderStatusDTO syncEntrustOrderStatusDTO) {
        updateEntrustOrderById(syncEntrustOrderStatusDTO.getEntrustOrder());
        return ResultDTO.success();
    }

    /*============================================*/
    /*============== private method ==============*/
    /*============================================*/
    /**
     * 检查订单是否存在：如果存在，返回该订单；否则抛出异常
     * @param entrustOrderId
     * @return
     * @throws OmsBaseException
     */
    private EntrustOrder validateEntrustOrderExist(Long entrustOrderId) throws OmsBaseException {
        EntrustOrder dbEntrustOrder = entrustOrderService.findByKey(entrustOrderId);
        if (dbEntrustOrder == null) {
            throw new OmsBaseException("订单不存在");
        }

        return dbEntrustOrder;
    }

    /**
     * 通过ID修改委托单
     * @param entrustOrder
     * @throws OmsBaseException
     */
    private void updateEntrustOrderById(EntrustOrder entrustOrder) {
        entrustOrderService.updateByKey(entrustOrder);
    }


}
